package com.sihai.ehr.service.impl;

import com.sihai.core.*;
import com.sihai.ehr.model.biz.*;
import com.sihai.ehr.model.sys.AuditStatus;
import com.sihai.ehr.model.sys.Organization;
import com.sihai.ehr.model.sys.OrganizationAuditing;
import com.sihai.ehr.repository.AuditingRepository;
import com.sihai.ehr.service.DutyProxyService;
import com.sihai.ehr.utils.DateUtil;
import org.apache.commons.lang.xwork.StringUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @author: wxn
 * @since: 12-6-16 下午2:26
 */
@Service("dutyProxyService")
public class DutyProxyServiceImpl implements DutyProxyService{
    @Resource
    private DataAccessor dataAccessor;

    @Resource
    private AuditingRepository auditingRepository;

    @Override
    public DutyProxy get(Long id) {
        if(id == null){
            return null;
        }
        return dataAccessor.get(DutyProxy.class, id);
    }

    @Override
    public LimitedList<DutyProxy> search(DutyProxy dutyProxy, Limit limit, Sorter sorter) {
        return null;
    }

    @Override
    public void save(DutyProxy dutyProxy) {
        if(dutyProxy == null){
            return;
        }
        dataAccessor.save(dutyProxy);

        if(dutyProxy.getProxyOne() != null && dutyProxy.getProxyOne().getId() != null){
            saveDutyProxyAuditings(dutyProxy, 1, 1);
        }
        if(dutyProxy.getProxyTwo() != null && dutyProxy.getProxyTwo().getId() != null){
            saveDutyProxyAuditings(dutyProxy, 1, 2);
        }
        if(dutyProxy.getProxyThree() != null && dutyProxy.getProxyThree().getId() != null){
            saveDutyProxyAuditings(dutyProxy, 1, 3);
        }
    }

    @Override
    public void remove(final String ids) {
        if(ids == null || ids.isEmpty()){
            return;
        }

        dataAccessor.batchUpdate(new QueryCreator() {
            @Override
            public Query createQuery(Session session) {
                return session.createQuery(String.format("update DutyProxy d set d.cancel = 1 where d.id in (%s)", ids));
            }
        });
    }

    @Override
    public LimitedList<DutyProxy> findByOrganization(Long organizationId, Limit limit, Sorter sorter) {
        if(organizationId == null){
            return null;
        }
        return dataAccessor.findByHql(DutyProxy.class, "from DutyProxy p where p.cancel <> 1 and p.duty.organization.id = ?", new Object[]{organizationId}, limit, sorter);
    }

    //查询职务代理审核流程列表
    @Override
    public List<List<DutyProxyAuditing>> findDutyProxyAuditings(Long id, int who) {
        return auditingRepository.findByHql(DutyProxyAuditing.class, "from DutyProxyAuditing da where da.who = ? and da.dutyProxy.id = ?", new Object[]{who, id});
    }

    //审核
    @Override
    public void saveDutyProxyAuditing(DutyProxyAuditing auditing, int who) {
        dataAccessor.save(auditing);

        boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

        DutyProxy dutyProxy = auditing.getDutyProxy();

        //审核结点状态改变后，清除本审核结点对象对应的消息
        deleteMessage(MessageType.duty_proxy, auditing.getDutyProxy().getId(), who);

        //如果未通过审核,则再创建一个审核流程
        if(isReject){
            saveDutyProxyAuditings(dutyProxy, auditing.getAuditNo() + 1, who);
        }else{
            AuditStatus status = auditing.isLast() ? AuditStatus.pass_audit : AuditStatus.within_audit;
            switch (who) {
                case 1: dutyProxy.setProxyOneStatus(status); break;
                case 2: dutyProxy.setProxyTowStatus(status); break;
                case 3: dutyProxy.setProxyThreeStatus(status); break;
            }
            dataAccessor.save(dutyProxy);

            sendDutyProxyMessage(auditing, who);
        }
    }

    @Override
    public void saveDutyProxyAuditingProcess(DutyProxy proxy, int who) {
        saveDutyProxyAuditings(dataAccessor.get(DutyProxy.class, proxy.getId()), 1, who);
    }

    @Override
    public DutyProxyAuditing getDutyProxyAuditing(Long id) {
        if(id == null){
            return null;
        }
        return dataAccessor.get(DutyProxyAuditing.class, id);
    }

    //创建审核流程
    private void saveDutyProxyAuditings(DutyProxy dutyProxy, int auditNo, int who) {
        Duty duty = dataAccessor.get(Duty.class, dutyProxy.getDuty().getId()); //如果是顶层
        Organization top = duty.getOrganization().getTopOrganization() == null ? duty.getOrganization() : duty.getOrganization().getTopOrganization();
        List<Auditing> audits = dataAccessor.findByHql(Auditing.class, "from Auditing a where a.auditingNo = ? and a.organization = ? order by a.id asc", new Object[]{AuditType.audit_duty_proxy, top}, null, null);
        if (audits != null && !audits.isEmpty()){
            DutyProxyAuditing first = null;
            int size = audits.size();
            for(int i = 0; i<size; i++){
                Auditing audit = audits.get(i);
                DutyProxyAuditing auditing = new DutyProxyAuditing();
                auditing.setDutyProxy(dutyProxy);
                auditing.setStatus(AuditStatus.wait_audit);
                auditing.setAuditing(audit);
                auditing.setAuditNo(auditNo);
                auditing.setWho(who);
                if(i == size -1){
                    auditing.setLast(true);
                }
                dataAccessor.save(auditing);
                if(i == 0){
                    first = auditing;
                }
            }
            //给第一个审核人发消息
            sendDutyProxyMessage(first, who);
        }
    }


    /**
     * 构建并发送职务代理审核消息
     * @param dutyProxy 要审核的职务代理
     * @param auditNode 审核流程中将要审核的结点
     */
    public void sendDutyProxyMessage(DutyProxyAuditing currentAuditNode, int who) {
        if(currentAuditNode == null || currentAuditNode.getDutyProxy() == null || currentAuditNode.getAuditing() == null){
            return;
        }

        DutyProxy dutyProxy = currentAuditNode.getDutyProxy();
        Auditing auditConfig = currentAuditNode.getAuditing();

        String displayName = dutyProxy.getDuty().getDutyName();
        if(StringUtils.isBlank(displayName)){
            Duty d = dataAccessor.get(Duty.class, dutyProxy.getDuty().getId());
            if(d != null){
                displayName = d.getDutyName();
            }
        }
        Duty duty = null;
        EmployeeinfoBase employee = null;
        int indicator = auditConfig.getIndicator();
        //1-指定人审核（employee）, 2-指定职务审核（duty,） 3-上级领导审核, 4-上上级领导审核
        if (indicator == 1) {
            employee = auditConfig.getEmployee();
        } else if (indicator == 2) {
            duty = auditConfig.getDuty();
        }else if(indicator == 3 || indicator == 4){
            List<AuditingBase> auditProcess = dataAccessor.findByHql(AuditingBase.class, "from DutyProxyAuditing a where a.auditNo = ? and a.dutyProxy = ? and a.who = ? order by a.id asc", new Object[]{currentAuditNode.getAuditNo(), dutyProxy, who}, null, null);
            duty = auditingRepository.findUpDuty(dutyProxy.getDuty(), auditProcess,currentAuditNode);
        }
        String url = String.format("duty_proxy/audit_detail.xhtml?proxy.id=%s&who=%s", dutyProxy.getId().longValue(), who);
        String[] data = {displayName, String.valueOf(who)};
        auditingRepository.saveMessage(MessageType.duty_proxy, url, dutyProxy.getId(), duty, employee, data);
    }

    private void deleteMessage(final MessageType type, final Long targetId, final int who){
        if(targetId == null){
            return;
        }
        dataAccessor.batchUpdate(new QueryCreator() {
            @Override
            public Query createQuery(Session session) {
                Query query = session.createQuery("delete from Message m where m.type=:mType and m.targetId=:targetId and m.data2 = :who");
                query.setParameter("mType", type);
                query.setParameter("targetId", targetId);
                query.setParameter("who", String.valueOf(who));
                return query;
            }
        });
    }
}
